package edu.chalmers.AV_2DPlatformerFramework.View;

import edu.chalmers.AV_2DPlatformerFramework.Model.GameModel;
import edu.chalmers.AV_2DPlatformerFramework.Model.GameObject;
import edu.chalmers.AV_2DPlatformerFramework.Model.Texture;
import edu.chalmers.AV_2DPlatformerFramework.Utility.Pair;
import edu.chalmers.AV_2DPlatformerFramework.Utility.Vector2D;
import java.awt.*;
import java.util.ArrayList; 
import javax.swing.JPanel;

/**
 * The superclass for the graphical component of the game. Relies on GameThread to call doUpdate.
 * @version 0.2
 * @author Richard
 * @revised Andrea, 21-04-2014: Refactoring to MVC pattern.
 */
public abstract class View extends JPanel{
    
    private GameModel model;
    public Camera camera;
        
    public void setModel(GameModel model) {
        this.model = model;
    }
    
    public GameModel getModel() {
        return this.model;
    } 
    
    /**
     * Draws a given GameObject using a given Graphics context.
     * @param g2d The Graphics context to use.
     * @param go The GameObject to draw.
     * @author Richard Sundqvist
     * @version 1.0
     */
    public void drawObject(Graphics2D g2d, GameObject go){
        Pair<Texture, Shape> visual = go.getVisual();
        g2d.setPaint(visual.getFirst());
        g2d.fill(visual.getSecond());    
    }
    /**
     * Draws a given GameObject's Hitbox using a given Graphics context.
     * @param g2d The Graphics context to use.
     * @param go The GameObject whose Hitbox is to be drawn.
     * @author Richard Sundqvist
     * @version 1.0
     */
    public void drawHitbox(Graphics2D g2d, GameObject go){      
        g2d.setColor(Color.RED);
        BasicStroke bs = new BasicStroke(2f);
        g2d.fill(bs.createStrokedShape(go.getHitboxVisual())); 
    }
    
    /**
     * Draws all ActiveObjects supplied by the model in use by this View.
     * @param g The Graphics context to draw on.
     * @author Richard Sundqvist
     * @version 1.0
     */
    public void drawActiveObjects(Graphics g){
        ArrayList<GameObject> objects = getModel().getActiveObjects();
        
        for(GameObject obj : objects)
            drawObject((Graphics2D) g, obj);
    }
    
    /**
     * Draws the Hitboxes of all active GameObjects, supplied by the GameModel in use by this View.
     * @param g The Graphics context to draw on.
     * @author Richard Sundqvist
     * @version 1.0
     */
    public void drawActiveObjectsHitboxes(Graphics g){
        ArrayList<GameObject> objects = getModel().getActiveObjects();
        
        for(GameObject obj : objects)
            drawHitbox((Graphics2D) g, obj);        
    }

    /**
     * The PaintComponent method does all the drawing on this View-JPanel.
     * From this method, you may call the different methods supplied by the
     * framework which will draw the various actors for you.
     * @param g Graphics context. Supplied by the JPanel superclass.
     */
    @Override
    public abstract void paintComponent(Graphics g);   
    
     /**
     * Draws the world relative to a given GameObject.
     * @param g The graphics context to draw on.
     * @param go The Object to follow.
     */
    public void drawActiveObjectsRelativeTo(Graphics g, GameObject go){
        ArrayList<GameObject> objects = getModel().getActiveObjects();
        camera.placeRelativeToObject(go);
        
        Vector2D actualPos;
            for(GameObject obj : objects){
                
                GameObject clone = obj.copy();
                clone.setPosition(camera.getRelativeCoordinatesFor(clone)); //Translated position
                drawObject((Graphics2D) g, clone);
                obj.getVisual(); //Solves AnimatedTexture issue.

            }
    }
        
    /**
     * Draws the world relative to a given GameObject's Hitbox.
     * @param g The graphics context to draw on.
     * @param go The Object to follow.
     */
    public void drawActiveObjectsHitboxesRelativeTo(Graphics g, GameObject go){
        ArrayList<GameObject> objects = getModel().getActiveObjects();
        
        Vector2D actualPos;
        for(GameObject obj : objects){
            GameObject clone = obj.copy();
            actualPos = clone.getPosition();
            clone.setPosition(camera.getRelativeCoordinatesFor(clone)); //Translated position
            
            drawHitbox((Graphics2D) g, clone); 
            clone.setPosition(actualPos);
        }
    }

    
}